package com.tp.interceptor;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.jfinal.kit.Ret;
import com.jfinal.log.Log;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.tp.base.BaseController;
import com.tp.model.sys.SysAuth;
import com.tp.model.sys.SysAuthUser;
import com.tp.model.sys.SysMenu;
import com.tp.model.sys.SysUser;
import com.tp.utils.Attr;
import com.tp.utils.IpUtils;
import com.tp.utils.StrUtils;
import com.tp.utils.WebUtils;

import org.apache.commons.lang.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.List;

/**
 * 用户认证拦截器
 *
 */
public class UserInterceptor implements Interceptor {

	private static final Log log = Log.getLog(UserInterceptor.class);

	@SuppressWarnings("rawtypes")
	public void intercept(Invocation ai) {
		Controller controller = ai.getController();

		HttpServletRequest request = controller.getRequest();
		String referrer = request.getHeader("referer");
		String site = "http://" + request.getServerName();
		log.warn("####IP:" + request.getRemoteAddr() + "\t port:" + request.getRemotePort() + "\t 请求路径:" + request.getRequestURI());

		StringBuffer paramsSb = new StringBuffer("");
		Enumeration enu = request.getParameterNames();
		if (null != enu) {
			while (enu.hasMoreElements()) {
				String paraName = (String) enu.nextElement();
				String paraVal = request.getParameter(paraName);
				paramsSb.append(paraName + ":" + paraVal + ", ");
			}
		}
		String ip = IpUtils.getClientIP(request);
		log.warn("访问者IP：" + ip);
		log.debug("####IP：" + ip + "\t port:" + request.getRemotePort() + "\t 请求路径:" + request.getRequestURI() + ", 参数:{" + paramsSb.toString() + "}");

		if (referrer == null || !referrer.startsWith(site)) {
			log.warn("####非法的请求");
		}
		
		String tmpPath = ai.getActionKey();
		if (tmpPath.startsWith("/")) {
			tmpPath = tmpPath.substring(1, tmpPath.length());
		}
		if (tmpPath.endsWith("/")) {
			tmpPath = tmpPath.substring(0, tmpPath.length() - 1);
		}
		String methodName = ai.getMethodName();

		// 每次访问获取session，没有可以从cookie取~
		SysUser user = null;
		if (controller instanceof BaseController) {
			user = ((BaseController) controller).getSessionUser();
		} else {
			user = controller.getSessionAttr(Attr.SESSION_NAME);
		}
		if (WebUtils.isBack(methodName)) {
			// 修复未登录情况时，直接前往某个路由报错问题
			if ((user == null || user.getId() <= 0) && (tmpPath.indexOf("/") > -1 || "home".equals(tmpPath))) {
				controller.redirect("/logout");
				return;
			}
			if (user == null || user.getId() <= 0) {
				controller.redirect("/trans");
				return;
			}
			// TODO 这里展示控制第三方用户和前端用户不能登录后台
			int usertype = user.getInt("usertype");
			if (usertype == 4 // 第三方用户
					|| usertype == 3) { // 前端用户
				controller.redirect("/trans/auth");
				return;
			}
			// TODO 判断url是否有权限
			if (!urlAuth(controller, tmpPath)) {
				controller.redirect("/trans/auth");
				return;
			}
		}
		// TODO 判断功能操作是否有权限
		if (!methodAuth(user, methodName, controller)) {
			//判断请求类型
			String requestType = ai.getController().getRequest().getHeader("X-Requested-With");
			if(StrUtils.isNotEmpty(requestType) && requestType.equals("XMLHttpRequest")){
				controller.renderJson(Ret.by("code", 2).set("msg", "操作权限不足，请联系管理员配置！"));
			}else{
				controller.redirect("/trans/auth");
			}
			return;
		}
		ai.invoke();
	}

	/**
	 * 判断Url是否有权限
	 *
	 * @param controller
	 * @param tmpPath
	 * @return
	 */
	protected boolean urlAuth(Controller controller, String tmpPath) {
		List<SysMenu> list = controller.getSessionAttr("nomenu");
		// nomenuList 应该是size等于0，而不是空
		if (list == null) {
			return false;
		}
		for (SysMenu sysMenu : list) {
			String url = sysMenu.getStr("url");
			if (StrUtils.isEmpty(url)) {
				continue;
			}
			if (tmpPath.startsWith(url)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 权限验证
	 *
	 * @param user
	 * @param tmpPath
	 * @return
	 */
	protected boolean methodAuth(SysUser user, String methodName, Controller controller) {
		SysAuth dao = new SysAuth();
		SysAuth userAuth = dao.findFirstByWhere("where url = ?", methodName);
		boolean has = false;
		if (null != userAuth && !"T".equalsIgnoreCase(userAuth.getStr("is_halt"))) {
			Integer userId = 1;
			if (null != user) {
				userId = user.getUserId();
			}
			String sql = "select t.* from " + SysAuthUser.tableName + " t where t.user_id = ?";
			Record rd = Db.findFirst(sql, userId);
			if (null != rd) {
				String urlAuth = rd.getStr("url_auth");
				if (userId == 1 && "*".equals(urlAuth)) {
					has = true;
				} else if (StringUtils.isNotBlank(urlAuth)) {
					urlAuth = ",".concat(urlAuth).concat(",");
					if (urlAuth.indexOf(",".concat(Long.toString(userAuth.getInt("id")).concat(","))) != -1) {
						has = true;
					}
				}
			}
		} else {
			has = true;
		}
		if (!has) {
			//controller.setAttr("msg", "[" + userAuth.getStr("descript") + "]" + "权限不足!");
			return false;
		}
		return true;
	}

}
